package org.ohos.rajawali3d.examples.examples.ui;

import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.components.webengine.WebAgent;
import ohos.agp.components.webengine.WebView;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.TextureHolder;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.opengl.Bitmap;
import opengl.platform.ohos.Log;
import org.ohos.rajawali3d.ResourceTable;
import org.ohos.rajawali3d.examples.examples.AExampleFragment;
import org.rajawali3d.Object3D;
import org.rajawali3d.animation.Animation;
import org.rajawali3d.animation.RotateOnAxisAnimation;
import org.rajawali3d.materials.Material;
import org.rajawali3d.materials.textures.ATexture;
import org.rajawali3d.materials.textures.StreamingTexture;
import org.rajawali3d.math.vector.Vector3;
import org.rajawali3d.primitives.Cube;

public class ViewToTextureFragment extends AExampleFragment implements TextureHolder.OnNewFrameCallback {

    FragmentToDraw mFragmentToDraw;
    EventHandler mHandler;
    private SurfaceProvider fragmentFrame;
    private PixelMapHolder mPixelMap;

    @Override
    public Component onCreateView(LayoutScatter inflater, ComponentContainer container, Intent savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        mHandler = new EventHandler(EventRunner.getMainEventRunner());
        fragmentFrame = new SurfaceProvider(getContext());
        final ComponentContainer.LayoutConfig params = new DirectionalLayout.LayoutConfig(200, 200);
        fragmentFrame.pinToZTop(true);
        fragmentFrame.setLayoutConfig(params);
       // WindowManager.getInstance().getTopWindow().get().setTransparent(true);
        mPixelMap = new PixelMapHolder(Bitmap.getPixelMapFromResource(ResourceTable.Media_webview, getContext()));

        return mLayout;
    }

    @Override
    public AExampleRenderer createRenderer() {
        return new ViewTextureRenderer(getContext(), this);
    }

    @Override
    protected void onBeforeApplyRenderer() {
        super.onBeforeApplyRenderer();
    }

    @Override
    public void onNewFrame(TextureHolder textureHolder) {
        Log.d("Render", "OnNewFrame arrived:" + textureHolder);
        mHandler.postTask(new Runnable() {
            @Override
            public void run() {
                fragmentFrame.addDrawTask(new Component.DrawTask() {
                    @Override
                    public void onDraw(Component component, Canvas canvas) {
                        canvas.save();
                        canvas.drawPixelMapHolder(mPixelMap, 0, 0, new Paint());
                        canvas.restore();
                    }
                });
            }
        });
    }

    private final class ViewTextureRenderer extends AExampleRenderer implements StreamingTexture.ISurfaceListener {
        private int mFrameCount;
        private Surface mSurface;
        //public Texture mTexture;
        private StreamingTexture mStreamingTexture;
        public volatile boolean mShouldUpdateTexture;

        private final float[] mMatrix = new float[16];

        public int colorI = 0;

        private Object3D mObject3D;

        ViewTextureRenderer(Context context, AExampleFragment fragment) {
            super(context, fragment);
        }

        //  @Override
        public void initScene() {
            mObject3D = new Cube(3.0f);
            mObject3D.setColor(0xFF000000);

            mObject3D.setPosition(0, 0, -3);
            mObject3D.setRenderChildrenAsBatch(true);

            mStreamingTexture = new StreamingTexture("viewTexture", this);
            Material material = new Material();
            material.setColorInfluence(0);
            // material.enableLighting(true);
            // material.setDiffuseMethod(new DiffuseMethod.Lambert());
            try {
                material.addTexture(mStreamingTexture);
            } catch (ATexture.TextureException e) {
                e.printStackTrace();
            }
            mObject3D.setMaterial(material);

            getCurrentScene().addChild(mObject3D);

            RotateOnAxisAnimation anim = new RotateOnAxisAnimation(Vector3.Axis.Y, 0,
                    360);
            anim.setRepeatMode(Animation.RepeatMode.INFINITE);
            anim.setDurationMilliseconds(12000);
            anim.setTransformable3D(mObject3D);
            getCurrentScene().registerAnimation(anim);
            anim.play();
        }

        final Runnable mUpdateTexture = new Runnable() {
            public void run() {
                // -- Draw the view on the canvas
                final Canvas canvas = mSurface.acquireCanvas();
                canvas.save();
                canvas.drawPixelMapHolder(mPixelMap, 0, 0, new Paint());
                canvas.restore();
                mSurface.syncCanvasDrawCalls();
//                int color_c = Integer.MAX_VALUE;
//                if (colorI > color_c)
//                    colorI = 0x11110011;
//                colorI = colorI + 0x11110011;
                // -- Indicates that the texture should be updated on the OpenGL thread.
                mShouldUpdateTexture = true;
            }
        };

        @Override
        protected void onRender(long elapsedRealtime, double deltaTime) {
            // -- not a really accurate way of doing things but you get the point :)
            if (mSurface != null && mFrameCount++ >= (mFrameRate * 0.25)) {
                mFrameCount = 0;
                mHandler.postTask(mUpdateTexture);
                mShouldUpdateTexture = true;
            }
            // -- update the texture because it is ready
            if (mShouldUpdateTexture) {
                mStreamingTexture.update();
                mShouldUpdateTexture = false;
            }
            //((ViewToTextureFragment)getExampleFragment()).onNewFrame(null);
            super.onRender(elapsedRealtime, deltaTime);
        }

        @Override
        public void setSurface(Surface surface) {
            mSurface = surface;
            mStreamingTexture.getSurfaceTexture().setBufferDimension(1024, 1024);
            mStreamingTexture.getSurfaceTexture().setOnNewFrameCallback(ViewToTextureFragment.this);
        }

        @Override
        public Surface getSurface() {
            return null;//getExampleFragment().getRenderSurface();
        }
    }

    public static final class FragmentToDraw extends ComponentContainer {

        WebView mWebView;
        SurfaceProvider mComponent;

        public FragmentToDraw(Context context) {
            super(context);
            mComponent = new SurfaceProvider(context);
            final ComponentContainer.LayoutConfig dparams = new DirectionalLayout.LayoutConfig();
            dparams.width = ComponentContainer.LayoutConfig.MATCH_PARENT;
            dparams.height = ComponentContainer.LayoutConfig.MATCH_PARENT;
            addComponent(mComponent, dparams);
        }

        public Component getComponent() {
            return mComponent;
        }

        public Component onComponentAttached(LayoutScatter inflater, ComponentContainer container, Intent intent) {
            final Component view = inflater.parse(ResourceTable.Layout_view_to_texture, container, false);
            mWebView = (WebView) view.findComponentById(ResourceTable.Id_webview);
            mWebView.setWebAgent(new WebAgent());
            mWebView.load("http://www.baidu.com");
            //mWebView.load("https://plus.google.com/communities/116529974266844528013");
            //mWebView.animate().rotationYBy(360.0f).setDuration(60000);
            view.setVisibility(Component.INVISIBLE);
            return view;
        }
    }
}
